﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using iTFF.WPF.AWSECommerceService;
using iTFF.WPF.Model.Artwork;
using System.Windows.Media.Imaging;
using System.Net;
using iTFF.WPF.Resources.Languages;
using System.ComponentModel;
using System.IO;

namespace iTFF.WPF.CP
{
    class ArtworksControlPanel
    {

        #region Fields

        private AmazonLocale[] _amazonLocales;

        #endregion

        #region Properties

        /// <summary>
        /// Gets a list of availables Amazon Locales
        /// </summary>
        public AmazonLocale[] AmazonLocales
        {
            get
            {
                if (_amazonLocales == null)
                    _amazonLocales = new AmazonLocale[] 
                {
                    new AmazonLocale("US", "United States (US)"),
                    new AmazonLocale("UK", "United Kingdom (UK)"),
                    new AmazonLocale("DE", "Germany (DE)"),
                    new AmazonLocale("JP", "Japan (JP)"),
                    new AmazonLocale("FR", "France (FR)"),
                    new AmazonLocale("CA", "Canada (CA)"),
                };

                return _amazonLocales;
            }
        }

        /// <summary>
        /// Gets or sets the selected Amazon Locale
        /// </summary>
        public AmazonLocale SelectedAmazonLocale
        {
            get
            {
                return AmazonLocales.FirstOrDefault(a => a.Code == Settings.Default.ArtworkAmazonLocale);
            }
            set
            {
                if (Settings.Default.ArtworkAmazonLocale != value.Code)
                    Settings.Default.ArtworkAmazonLocale = value.Code;
            }
        }

        #endregion

        #region Private Helpers

        /// <summary>
        /// Gets the Amazon Web Service access key
        /// </summary>
        public string AccessKey
        {
            get
            {
                return ConfigurationManager.AppSettings["AmazonAccessKey"];
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Gets a list of artworks for the specified keywords. Images aren't yet downloaded.
        /// </summary>
        /// <param name="keywords"></param>
        /// <returns></returns>
        public List<Artwork> GetArtworks(string keywords)
        {
            return GetArtworks(null, keywords);
        }

        /// <summary>
        /// Gets a list of artworks for the specified keywords. Images aren't yet downloaded.
        /// </summary>
        /// <param name="bw">Makes cancelation available</param>
        /// <param name="keywords"></param>
        /// <returns></returns>
        public List<Artwork> GetArtworks(BackgroundWorker bw, string keywords)
        {

            // instantiate the client depending on the Culture Settings
            string endpoint = "AWSECommerceServicePort_{0}";

            AWSECommerceServicePortTypeClient awse;

            if (!string.IsNullOrEmpty(Settings.Default.ArtworkAmazonLocale))
            {
                endpoint = string.Format(endpoint, Settings.Default.ArtworkAmazonLocale);

                try
                {
                    awse = new AWSECommerceServicePortTypeClient(endpoint);
                }
                catch (InvalidOperationException)
                {
                    // means that the amzon locale isn't correct because it isn't linked with any configuration endpoint
                    throw new ApplicationException(Strings.ArtworkCPCultureIncorrect);
                }
            }
            else
                throw new ApplicationException(Strings.ArtworkCPCultureIncorrect);

            var covers = new List<Artwork>();

            // initialize item search
            ItemSearch search = new ItemSearch();
            search.AWSAccessKeyId = AccessKey;

            // create request
            ItemSearchRequest request = new ItemSearchRequest();

            // Fill request object with request parameters : Medium-sized images
            request.ResponseGroup = new string[] { "ItemAttributes", "Images" };

            // Set SearchIndex and Keywords 
            request.SearchIndex = "Music";
            request.Keywords = keywords;

            // Set the request on the search wrapper
            search.Request = new ItemSearchRequest[] { request };

            //Send the request and store the response 
            ItemSearchResponse response = awse.ItemSearch(search);

            if (bw != null && bw.CancellationPending)
                return null;

            foreach (Items items in response.Items)
            {
                if (items.Item == null)
                    return null;

                foreach (Item item in items.Item)
                {

                    if (item.ItemAttributes != null && item.MediumImage != null)
                    {

                        string artist = null;
                        if (item.ItemAttributes.Artist != null)
                            artist = string.Join(" - ", item.ItemAttributes.Artist);

                        Artwork cover = new Artwork
                        {
                            Album = item.ItemAttributes.Title,
                            Artist = artist,
                            ReleaseDate = item.ItemAttributes.ReleaseDate,
                            ImageURLMedium = item.MediumImage == null ? null : item.MediumImage.URL,
                            ImageURLBig = item.LargeImage == null ? null : item.LargeImage.URL
                        };

                        covers.Add(cover);
                    }
                }
            }

            return covers;
        }

        /// <summary>
        /// Downloads Medium Image for the artwork.
        /// </summary>
        /// <param name="artwork"></param>
        /// <exception cref="System.ApplicationException" />
        public Stream DownloadMediumImage(Artwork artwork)
        {
            try
            {
                if (!string.IsNullOrEmpty(artwork.ImageURLMedium))
                    return GetImageStream(artwork.ImageURLMedium);
                else
                    throw new ArgumentException("artwork.ImageURLMedium");
            }
            catch (WebException e)
            {
                throw new ApplicationException(string.Format(Strings.ArtworkCPCannotDownloadImage, Environment.NewLine, e.Message));
            }
        }

        /// <summary>
        /// Downloads Big Image for the artwork.
        /// </summary>
        /// <param name="artwork"></param>
        /// <exception cref="System.ApplicationException" />
        public Stream DownloadBigImage(Artwork artwork)
        {
            try
            {
                if (!string.IsNullOrEmpty(artwork.ImageURLBig))
                    return GetImageStream(artwork.ImageURLBig);
                else
                    throw new ArgumentException("artwork.ImageURLBig");
            }
            catch (WebException e)
            {
                throw new ApplicationException(string.Format(Strings.ArtworkCPCannotDownloadImage, Environment.NewLine, e.Message));
            }
        }

        /// <summary>
        /// Downloads the image to a temporary file
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public string DownloadImageToTempFile(string url)
        {
            if (string.IsNullOrEmpty(url))
                throw new ArgumentNullException("url");

            try
            {
                var temp = Path.GetTempFileName();
                new WebClient().DownloadFile(url, temp);
                return temp;
            }
            catch (WebException e)
            {
                throw new ApplicationException(string.Format(Strings.ArtworkCPCannotDownloadImage, Environment.NewLine, e.Message));
            }
            catch (IOException e)
            {
                throw new ApplicationException(string.Format(Strings.ArtworksCPCreateTempIOException, e.Message));
            }
            catch (UnauthorizedAccessException e)
            {
                throw new ApplicationException(string.Format(Strings.ArtworksCPCreateTempUnauthorizedAccessException, e.Message));
            }
            catch (System.Security.SecurityException e)
            {
                throw new ApplicationException(string.Format(Strings.ArtworksCPCreateTempUnauthorizedAccessException, e.Message));
            }
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Downloads an image and stores it into a MemoryStream
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        /// <exception cref="System.Web.WebException" />
        MemoryStream GetImageStream(string url)
        {
            MemoryStream stream = new MemoryStream();

            var resp = WebRequest.Create(url).GetResponse();
            var respStream = resp.GetResponseStream();

            byte[] buffer = new byte[resp.ContentLength];
            respStream.Read(buffer, 0, (int)resp.ContentLength);
            stream.Write(buffer, 0, (int)resp.ContentLength);
            stream.Seek(0, SeekOrigin.Begin);

            return stream;
        }

        #endregion
    }
}
